//
// Created by makui on 2024/12/22.
//

#ifndef ENTITY_HPP
#define ENTITY_HPP

#include <boost/pfr.hpp> // 替换为 magic_get 如果你使用的是该库

#include "mysqlx/xdevapi.h"
#include "common/utils.hpp"
#include "common/macros.hpp"

namespace common {

// 泛型模板，当不需要特殊处理时直接返回原值
template <class T>
T to_type(T&& origin) {
    return std::forward<T>(origin);
}

// 特化版本，用于从 std::vector<uint8_t> 转换到 mysqlx::bytes
mysqlx::bytes to_type(const std::vector<uint8_t>&& origin) {
    return mysqlx::bytes(origin.data(), origin.size());
}

template<typename... Args>
auto to_database_helper(mysqlx::Table &table, Args&&... args) {
    return table.insert(split(LINK_STRINGS_WITH_COMMA(__VA_ARGS__), ",")).values(
        (to_type(std::forward<Args>(args)), ...));
}


#define ENTITY_REGISTRY(...) \
public: \
    void to_database(mysqlx::Table table) { \
        to_database_helper(table, __VA_ARGS__); \
    } \
    void from_database(mysqlx::Row row) { \
        if (row.isNull()) return; \
        boost::pfr::for_each_field(*this, [i = 0, &row](auto& member) mutable { \
            using T = std::decay_t<decltype(member)>; \
            if constexpr (std::is_same_v<T, std::string>) { \
                member = row[i].get<std::string>(); \
            } else if constexpr (std::is_same_v<T, std::vector<uint8_t>>) { \
                auto temp = row[i].getRawBytes(); \
                member.assign(temp.begin(), temp.end()); \
            } else { member = row[i]; } \
            ++i; \
        }); \
    }

}

#endif //ENTITY_HPP
